/**
	@file printstr.S
	@author Andrew D. Zonenberg
	@brief Prints a string to the UART
 */
 
.set noreorder					/*	Prevent any optimizations from reordering instructions!
									We want exe to exactly match source! */

/*
	Program entry point
 */
.section .startup.bootvec, "ax", @progbits 
.globl _start
_start:
	jal			uartInit			/*	Initialize the UART before doing anything else */

	la			$a0, mystr			/*	Get a pointer to the string */
	jal			printStr			/*	and print it */
	
	j			echo				/*	then just echo everything we type */

/*
	Initialize the UART 
 */
.section .startup, "ax", @progbits
uartInit:
	la			$t0, U1BRG
	li			$t1, 868			/*	100 MHz / 115200 bps */
	sw			$t1, 0($t0)
	jr			$ra

/*
	Prints a null-terminated string to the UART
 */
printStr:
	la			$t0, U1TXBUF			/*	Write all of our transmit data here */
	la			$t2, U1STAT				/* 	UART status register */

.txloop:
	lw			$t3, 0($t2)				/*	Read status register */
	andi		$t3, 0x4				/*	Check for txfifo_full bit */
	beq			$t3, $zero, .doprint	/*	If not set, just print it */
.busywait:
	lw			$t3, 0($t2)				/*	Read status register */
	andi		$t3, 0x8				/*	Check for txfifo_empty bit */
	beq			$t3, $zero, .busywait	/*	If not set, go back and do it again.
											Otherwise fall through to doPrint */

.doprint:
	lb			$t1, 0($a0)				/*	Read from the string */
	beq			$t1, $zero, .done		/*	If it's a null character, we're done */
	sb			$t1, 0($t0)
	
	addi		$a0, $a0, 1				/*	Go on to the next character */
	j			.txloop
	nop
	nop
	
.done:
	jr			$ra
	
/*
	Infinite loop printing stuff as it comes in
 */
echo:
	la			$t0, U1TXBUF			/*	Write all of our transmit data here */
	la			$t2, U1STAT				/* 	UART status register */
	la			$t4, U1RXBUF			/*	Read buffer */
	
.rxloop:
	lw			$t3, 0($t2)				/*	Read status register */
	
	andi		$t3, 0x400				/*	Check for rxfifo_empty bit */
	bne			$t3, $zero, .rxloop		/*	If set, go back and do it again */

.tbusywait:
	lw			$t3, 0($t2)				/*	Read status register */
	andi		$t3, 0x4				/*	Check for txfifo_full bit */
	bne			$t3, $zero, .tbusywait	/*	If set, go back and do it again.
											Otherwise fall through and print */

	lb			$t5, 0($t4)				/*	Read the byte from the UART */
	sb			$t5, 0($t0)				/*	and echo it */

	j			echo

/*
	Everything below here is data (no code)
 */
mystr:
	.asciiz "ACHD SoC v0.1 starting up...\r\nHello World!\r\nAll keystrokes should be echoed to the console.\r\n"
